
#include "bb_protocol.h"
#include "gkt_crc8.h"
#include "gkt_systime.h"
#include "gkt_uart.h"
#include "gkt_debug.h"

#ifdef GKT_CONFIG_BB_NETWORK_SEND_MAXTIMES
#define BB_NETWORK_SEND_MAXTIMES	\
	GKT_CONFIG_BB_NETWORK_SEND_MAXTIMES
#else
#define BB_NETWORK_SEND_MAXTIMES	3
#endif

int bb_network_send_packet(uint8_t *payload_buff, uint32_t length)
{
	uint8_t *net_packet;
	uint32_t net_packet_len;
	int retval, loops;

	net_packet = payload_buff - BB_NETWORK_PAYLOAD_OFFSET;
	gkt_store_be24(net_packet, BB_NETWORK_PREAMBLE);
	net_packet[BB_NETWORK_LENGTH_OFFSET] = (uint8_t)length;
	net_packet[BB_NETWORK_PAYLOAD_OFFSET + length] = gkt_crc8(payload_buff, length);

	net_packet_len = BB_NETWORK_PAYLOAD_OFFSET + length + BB_NETWORK_CRC_SIZE;

	retval = BB_TRANSPORT_ITEM(CTL, payload_buff[BB_TRANSPORT_CTL_SI_OFFSET]);
	if (0x02 != retval) { //0x02 - BB_TRANSPORT_CTL_CFG_PACKET
#if 0
		gkt_info("send: net_packet_len(%d), net_packet:", net_packet_len);
		for (int i=0; i<net_packet_len; i++) {
			gkt_printf("0x%02x ", net_packet[i]);
		}
		gkt_printf("\n");
#endif
	}

	loops = 0;
	do {
		retval = gkt_uart_send(GKT_CONFIG_BACKBOARD_UART_ID, 
						net_packet, net_packet_len, 100);

		if (GKT_SUCCESS == retval)
			break;
		else
			gkt_error("bb_network_send_packet: gkt_uart_send failed, retval(%d)\n", retval);

		gkt_delay_us(10);
	} while (++loops < BB_NETWORK_SEND_MAXTIMES);

	return retval;
}

void bb_network_packet_received(const uint8_t *data, 
				uint32_t length)
{
	const uint8_t *net_packet_data, *net_payload;
	uint32_t preamble, offset, net_packet_len;
	uint8_t net_payload_len, crc8_fetch, crc8_calc;
#if 0
	gkt_info("received: length(%d), net_payload:", length);
	for (int i=0; i<length; i++) {
		gkt_printf("0x%02x ", data[i]);
	}
	gkt_printf("\n");
#endif
	offset = 0;
	while ((offset + GKT_PACKET_MINSIZE) <= length) {
		net_packet_data = &data[offset];
		
		preamble = gkt_fetch_be24(&net_packet_data[BB_NETWORK_PREAMBLE_OFFSET]);
		if (preamble != BB_NETWORK_PREAMBLE) {
			offset++;
			continue;
		}

		net_payload_len = net_packet_data[BB_NETWORK_LENGTH_OFFSET];
		net_packet_len = BB_NETWORK_PAYLOAD_OFFSET + net_payload_len + BB_NETWORK_CRC_SIZE;
		if ((offset + net_packet_len) <= length) {
			net_payload = &net_packet_data[BB_NETWORK_PAYLOAD_OFFSET];

			crc8_calc = gkt_crc8(net_payload, net_payload_len);
			crc8_fetch = net_packet_data[BB_NETWORK_PAYLOAD_OFFSET + net_payload_len];
			if (crc8_calc == crc8_fetch) 
				bb_transport_packet_received(net_payload, net_payload_len);
			else {
				gkt_error("net_packet: [%u] crc8(0x%x-0x%x) unmatch!\n", 
					offset, crc8_calc, crc8_fetch);
			}

			offset += net_packet_len;
		}
		else
			break;	/* incomplete network packet */
	}

	if (offset < length) {
		// TODO: data surplus
	}
}

int bb_network_init(void)
{
	return GKT_SUCCESS;
}

